#include "escriba.h"

Escriba::Escriba(Sentencia *next, vector<string> variables, Expr *var, int fila, int col):Sentencia(next,fila,col)
{
    this->variables = variables;
    this->var=var;
}

string Escriba::is()
{
    return "ESCRIBA";
}

void Escriba::setVariables(vector<string> variables)
{
    this->variables=variables;
}

vector<string> Escriba::getVariables()
{
    return this->variables;
}

void Escriba::setVar(Expr *var)
{
    this->var = var;
}

Expr *Escriba::getVar()
{
    return this->var;
}

Tipo_ts *Escriba::validarSemantica(Tabla_Simbolos *tabla_de_tipo, Tabla_Simbolos *tabla_de_varaible)
{

    Tipo_ts *tts;
    for(int i=0;i<this->getVariables().size();i++){
        tts = tabla_de_varaible->get(this->getVariables().at(i))->getTipo();
        if(tts!=0){
        if(tts->is().compare("PIN")!=0){
            stringstream out;
            out << "Variable No es de Tipo PIN " <<this->getVariables().at(i) <<" Columna: "<<this->getCol()<< " Fila: "<<this->getFila();
            throw  exception(out.str().c_str());
        }else{
            Pin *p = (Pin*)tts;
            if(p->getModo()==1){
                stringstream out;
                out << "PIN tiene que ser de salida" <<this->getVariables().at(i) <<" Columna: "<<this->getCol()<< " Fila: "<<this->getFila();
                throw  exception(out.str().c_str());
            }
        }
        }else{
            stringstream out;
            out << "Variable No Existe " <<this->getVariables().at(i) <<" Columna: "<<this->getCol()<< " Fila: "<<this->getFila();
            throw  exception(out.str().c_str());
        }
    }

    if(this->var->is().compare("var_pin")==0){
        PinVariable *pv = (PinVariable*)this->var;
        Tipo_ts *ts = tabla_de_varaible->get(pv->getValor())->getTipo();
        if(ts->is().compare("ENTERO")!=0){
            stringstream out;
            out << "Varaible debe de ser Entera " <<pv->getValor() <<" Columna: "<<this->getCol()<< " Fila: "<<this->getFila();
            throw  exception(out.str().c_str());
        }else{
            pv->validarSemantica(tabla_de_tipo,tabla_de_varaible);
        }

    }


    if(this->getNext()!=0){
        this->getNext()->SetReturn(this->GetReturn());
        this->getNext()->validarSemantica(tabla_de_tipo,tabla_de_varaible);
    }
    return 0;
}

string Escriba::generarCodigo(GenerarVariable *var, Tabla_Simbolos *tabla_de_tipo, Tabla_Simbolos *tabla_de_varaible)
{
    string codigo;
    if(this->var->is().compare("var_pin")==0){
    string inicio = var->getNewVariable("inicio");
    string final = var->getNewVariable("final");
    string temp = var->getNewVariable("temp");
    PinVariable *pv = (PinVariable*)this->var;
    codigo = "\nint "+ inicio+" = "+pv->getInicio()->generarCodigo(var,tabla_de_tipo,tabla_de_varaible).codigo+";\n";
    codigo += "int "+final+" = "+pv->getFin()->generarCodigo(var,tabla_de_tipo,tabla_de_varaible).codigo+";\n";
    codigo += "int "+temp+" = "+ inicio+";\n";
    for(int i=0;i<this->variables.size();i++){
        Pin *pin_ =(Pin*)tabla_de_varaible->get(this->variables.at(i))->getTipo();
        this->it4 = this->pinescribir.find(pin_->getPin());
        this->it = this->pindir.find(pin_->getPin());
        QString n;
        n.setNum(this->it->second,10);
        codigo += "if("+inicio+" < "+final+"){\n";
        codigo += "if(_"+pv->getValor()+"_ & (1 << "+temp+")){\n" ;
        codigo += this->it4->second+" |= 1 << "+n.toStdString()+";\n";
        codigo += "}else{\n";
        codigo += this->it4->second+" &= ~ (1 << "+n.toStdString()+")\n;";
        codigo +="}\n";
        codigo +=temp+"++;";
        codigo += "}else{\n";
        codigo += "if(_"+pv->getValor()+"_ & (1 << "+temp+")){\n" ;
        codigo += this->it4->second+" |= 1 << "+n.toStdString()+";\n";
        codigo += "}else{\n";
        codigo += this->it4->second+" &= ~ (1 << "+n.toStdString()+");\n";
        codigo +="}\n";
        codigo +=temp+"--;";
        codigo+="}\n";

    }
    }else{
        TipoDato *td = (TipoDato*)this->var;
        string valor = td->getValor();
        if(valor.compare("1")){
            for(int i=0;i<this->variables.size();i++){
                Pin *pin_ =(Pin*)tabla_de_varaible->get(this->variables.at(i))->getTipo();
                this->it4 = this->pinescribir.find(pin_->getPin());
                this->it = this->pindir.find(pin_->getPin());
                QString n;
                n.setNum(this->it->second,10);
                codigo+= this->it4->second+" |= 1 << "+n.toStdString()+";\n";
            }

        }else{

            for(int i=0;i<this->variables.size();i++){
                Pin *pin_ =(Pin*)tabla_de_varaible->get(this->variables.at(i))->getTipo();
                this->it4 = this->pinescribir.find(pin_->getPin());
                this->it = this->pindir.find(pin_->getPin());
                QString n;
                n.setNum(this->it->second,10);
                codigo += this->it4->second+" &= ~ (1 << "+n.toStdString()+");\n";
            }

        }


    }
    if(this->getNext()!=0){
        codigo += this->getNext()->generarCodigo(var,tabla_de_tipo,tabla_de_varaible);
    }

    return codigo;
}
